package com.tj.collection.controller.lending.response;

import com.alibaba.fastjson.JSON;
import com.fqgj.common.api.ResponseData;
import com.fqgj.common.utils.*;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.jsoniter.output.JsonStream;
import com.tj.collection.db.entity.ClMerchantEntity;
import com.tj.collection.db.entity.ClReceiverEntity;
import com.tj.collection.db.entity.business.ClAllocationInfoEntity;
import com.tj.collection.db.entity.business.ClCountInfoEntity;
import com.tj.collection.utils.CalculatorUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: pavan
 * Date: 2019/9/10
 * Time: 下午5:57
 */
public class ClQueryResponse implements ResponseData {
    private static final Log LOGGER = LogFactory.getLog(ClQueryResponse.class);

    private List<Item> itemList = new ArrayList<>();

    private CountItem countInfo;

    public ClQueryResponse(List<ClAllocationInfoEntity> clAllocationInfoEntityList, ClCountInfoEntity clCountInfoEntity, List<ClMerchantEntity> clMerchantEntityList, List<ClReceiverEntity> clReceiverEntities) {
        LOGGER.info("== clCountInfoEntity ==,json:{}", JsonStream.serialize(clCountInfoEntity));
        if (CollectionUtils.isEmpty(clReceiverEntities)) {
            return;
        }
        Map<String, ClMerchantEntity> merchantMap = EntityUtils.makeEntityMap(clMerchantEntityList, "merchantCode");
        Map<String, ClReceiverEntity> receiverEntityMap = EntityUtils.makeEntityMap(clReceiverEntities, "collectionNo");
        for (ClAllocationInfoEntity clAllocationInfoEntity : clAllocationInfoEntityList) {
            String appName = clAllocationInfoEntity.getAppName();
            if (StringUtils.isEmpty(appName)) {
                appName = clAllocationInfoEntity.getOrderSource();
            }
            if (StringUtils.isEmpty(appName)) {
                appName = merchantMap.containsKey(clAllocationInfoEntity.getSourceMerchantCode()) ? merchantMap.get(clAllocationInfoEntity.getSourceMerchantCode()).getAppName() : clAllocationInfoEntity.getSourceMerchantCode();
            }

            Item item = new Item()
                    .setAppName(appName)
                    .setSourceMerchantCode(clAllocationInfoEntity.getSourceMerchantCode())
                    .setProductCategory(clAllocationInfoEntity.getProductType())
                    .setChannel(clAllocationInfoEntity.getChannel())
                    .setName(clAllocationInfoEntity.getName())
                    .setMobile(clAllocationInfoEntity.getMobile())
                    .setPeriod(clAllocationInfoEntity.getPeriod() + "")
                    .setTotalPeriod(clAllocationInfoEntity.getTotalPeriod())
                    .setFollowDays(clAllocationInfoEntity.getLastHandleTime() == null ? null : DateUtil.diffDate(new Date(), clAllocationInfoEntity.getLastHandleTime()))
                    .setCollectionStatus("--")
                    .setOriginNo(receiverEntityMap.get(clAllocationInfoEntity.getCollectionNo()).getOriginNo())
                    .setTradeNo(clAllocationInfoEntity.getOrderNo())
                    .setUserCode(clAllocationInfoEntity.getUserCode())
                    .setCollectionNo(clAllocationInfoEntity.getCollectionNo())
                    .setFollowId(clAllocationInfoEntity.getAdminId())
                    .setFollowUp(clAllocationInfoEntity.getAgentName())
                    .setCollectionOrderDetailVoList(new ArrayList<>())
                    .setMaxOverdueDays(clAllocationInfoEntity.getOverdueDays())
                    .setOverdueDays(clAllocationInfoEntity.getOverdueDays())
                    .setCity(clAllocationInfoEntity.getCity())
                    .setFollowTime(clAllocationInfoEntity.getLastHandleTime() == null ? null : DateUtil.getDate(clAllocationInfoEntity.getLastHandleTime(), "yyyy-MM-dd HH:mm:ss"))
                    .setNextTime(clAllocationInfoEntity.getNextTime() == null ? null : DateUtil.getDate(clAllocationInfoEntity.getNextTime(), "yyyy-MM-dd HH:mm:ss"));
            item.setProductCategoryName(item.getAppName());

            //账单描述信息
            List<BillItem> billItems = new ArrayList<>();
            BigDecimal expireAmount = new BigDecimal(0);//总应还
            BigDecimal noRepayAmount = new BigDecimal(0);
            BigDecimal lateFee = new BigDecimal(0);
            BigDecimal overdueServiceFee = BigDecimal.ZERO;
            BigDecimal overdueFee = BigDecimal.ZERO;
            if (clAllocationInfoEntity.getOverdueDays() > 0) {
                int overdueDays = CalculatorUtils.overDueDays(clAllocationInfoEntity.getRepaymentDate(), new Date());
                overdueServiceFee = clAllocationInfoEntity.getLateServiceFee();
                if (clAllocationInfoEntity.getRemainMoney().compareTo(BigDecimal.ZERO) == 0) {
                    overdueFee = CalculatorUtils.calculateOverdueFee(clAllocationInfoEntity.getBorrowCapital(), clAllocationInfoEntity.getLateFeeRatio(), overdueDays);
                } else {
                    overdueFee = BigDecimal.ZERO;
                }
            }

            lateFee = overdueFee.add(overdueServiceFee);
            if (clAllocationInfoEntity.getRemainMoney().compareTo(BigDecimal.ZERO) == 0) {
                overdueFee = BigDecimal.ZERO;
            }
            if (clAllocationInfoEntity.getRemainMoney().compareTo(BigDecimal.ZERO) == 0) {
                expireAmount = CalculatorUtils.repaymentTotalCapital(clAllocationInfoEntity.getBorrowCapital(), clAllocationInfoEntity.getInterest(), overdueFee, overdueServiceFee);
            } else {
                expireAmount = clAllocationInfoEntity.getTotalMoney();
            }
            if (clAllocationInfoEntity.getRemainMoney().compareTo(BigDecimal.ZERO) == 0) {
                noRepayAmount = expireAmount.subtract(clAllocationInfoEntity.getPaidAmount()).subtract(clAllocationInfoEntity.getDeductAmount());
            } else {
                noRepayAmount = clAllocationInfoEntity.getRemainMoney();
            }
            if (noRepayAmount.compareTo(BigDecimal.ZERO) < 0) {
                noRepayAmount = BigDecimal.ZERO;
            }

            expireAmount = expireAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
            noRepayAmount = noRepayAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
            lateFee = lateFee.setScale(2, BigDecimal.ROUND_HALF_UP);

            BillItem billItem = new BillItem()
                    .setTradeNo(clAllocationInfoEntity.getOrderNo())
                    .setPeriod(clAllocationInfoEntity.getPeriod())
                    .setRepaymentDate(DateUtil.getDate(clAllocationInfoEntity.getRepaymentDate(), "yyyy-MM-dd"))
                    .setRealCapital(clAllocationInfoEntity.getBorrowCapital())
                    .setInterest(clAllocationInfoEntity.getInterest())
                    .setLateFee(lateFee)
                    .setNoRepayAmount(noRepayAmount)
                    .setExpireAmount(expireAmount)
                    .setOverdueDays(clAllocationInfoEntity.getOverdueDays())
                    .setActualRepaymentDate(clAllocationInfoEntity.getActualRepaymentDate() == null ? "" : DateUtil.getDate(clAllocationInfoEntity.getActualRepaymentDate(), "yyyy-MM-dd HH:mm:ss"))
                    .setPaidAmount(clAllocationInfoEntity.getPaidAmount())
                    .setDeductAmount(clAllocationInfoEntity.getDeductAmount());
            billItems.add(billItem);

            item.setNoRepayAmount(noRepayAmount.stripTrailingZeros().toPlainString());
            item.setCollectionOrderDetailVoList(billItems);


            this.itemList.add(item);
        }

        this.countInfo = new CountItem();
        if (clCountInfoEntity != null) {
            try {
                this.countInfo.setTotalCount(clCountInfoEntity.getCompletedCount() + clCountInfoEntity.getUnfinishedCount());
                this.countInfo.setCompletedCount(clCountInfoEntity.getCompletedCount());
                this.countInfo.setUnfinishedCount(clCountInfoEntity.getUnfinishedCount());
                this.countInfo.setInvalidCount(0);
                this.countInfo.setCompletionRate(DecimalUtils.round(clCountInfoEntity.getCompletedCount().doubleValue() * 100 / (clCountInfoEntity.getCompletedCount() + clCountInfoEntity.getUnfinishedCount()), 2).toString() + " %");
            } catch (Exception e) {
                LOGGER.warn("转换催收统计数据失败,clCountInfoEntity:{}", JSON.toJSONString(clCountInfoEntity), e);
            }
        }
    }

    private class Item {
        /**
         * 应用名称
         */
        private String appName;

        private String originNo;


        /**
         * 商户号
         */
        private String sourceMerchantCode;

        private String productCategory;

        private String productCategoryName;

        private String channel;

        private String name;

        private String mobile;

        private String period;

        private Integer totalPeriod;

        private String collectionStatus;

        private Integer followDays;

        private Integer collectionType;

        private String collectionNo;

        private String tradeNo;

        private String userCode;

        private Integer followId;

        private String followUp;

        private Integer maxOverdueDays;

        private Integer overdueDays;

        private String city;

        /**
         * 工单跟进时间
         */
        private String followTime;
        /**
         * 约定时间
         */
        private String nextTime;

        /**
         * 剩余应还金额
         */
        private String noRepayAmount;

        private List<BillItem> collectionOrderDetailVoList;


        public String getAppName() {
            return appName;
        }

        public Item setAppName(String appName) {
            this.appName = appName;
            return this;
        }

        public String getOriginNo() {
            return originNo;
        }

        public Item setOriginNo(String originNo) {
            this.originNo = originNo;
            return this;
        }

        public String getSourceMerchantCode() {
            return sourceMerchantCode;
        }

        public Item setSourceMerchantCode(String sourceMerchantCode) {
            this.sourceMerchantCode = sourceMerchantCode;
            return this;
        }

        public String getProductCategory() {
            return productCategory;
        }

        public Item setProductCategory(String productCategory) {
            this.productCategory = productCategory;
            return this;
        }

        public String getProductCategoryName() {
            return productCategoryName;
        }

        public Item setProductCategoryName(String productCategoryName) {
            this.productCategoryName = productCategoryName;
            return this;
        }

        public String getChannel() {
            return channel;
        }

        public Item setChannel(String channel) {
            this.channel = channel;
            return this;
        }

        public String getName() {
            return name;
        }

        public Item setName(String name) {
            this.name = name;
            return this;
        }

        public String getMobile() {
            return mobile;
        }

        public Item setMobile(String mobile) {
            this.mobile = mobile;
            return this;
        }

        public String getPeriod() {
            return period;
        }

        public Item setPeriod(String period) {
            this.period = period;
            return this;
        }

        public Integer getTotalPeriod() {
            return totalPeriod;
        }

        public Item setTotalPeriod(Integer totalPeriod) {
            this.totalPeriod = totalPeriod;
            return this;
        }

        public String getCollectionStatus() {
            return collectionStatus;
        }

        public Item setCollectionStatus(String collectionStatus) {
            this.collectionStatus = collectionStatus;
            return this;
        }

        public Integer getFollowDays() {
            return followDays;
        }

        public Item setFollowDays(Integer followDays) {
            this.followDays = followDays;
            return this;
        }

        public Integer getCollectionType() {
            return collectionType;
        }

        public Item setCollectionType(Integer collectionType) {
            this.collectionType = collectionType;
            return this;
        }

        public String getCollectionNo() {
            return collectionNo;
        }

        public Item setCollectionNo(String collectionNo) {
            this.collectionNo = collectionNo;
            return this;
        }

        public String getTradeNo() {
            return tradeNo;
        }

        public Item setTradeNo(String tradeNo) {
            this.tradeNo = tradeNo;
            return this;
        }

        public String getUserCode() {
            return userCode;
        }

        public Item setUserCode(String userCode) {
            this.userCode = userCode;
            return this;
        }

        public Integer getFollowId() {
            return followId;
        }

        public Item setFollowId(Integer followId) {
            this.followId = followId;
            return this;
        }

        public String getFollowUp() {
            return followUp;
        }

        public Item setFollowUp(String followUp) {
            this.followUp = followUp;
            return this;
        }

        public Integer getMaxOverdueDays() {
            return maxOverdueDays;
        }

        public Item setMaxOverdueDays(Integer maxOverdueDays) {
            this.maxOverdueDays = maxOverdueDays;
            return this;
        }

        public Integer getOverdueDays() {
            return overdueDays;
        }

        public Item setOverdueDays(Integer overdueDays) {
            this.overdueDays = overdueDays;
            return this;
        }

        public String getCity() {
            return city;
        }

        public Item setCity(String city) {
            this.city = city;
            return this;
        }

        public String getFollowTime() {
            return followTime;
        }

        public Item setFollowTime(String followTime) {
            this.followTime = followTime;
            return this;
        }

        public String getNextTime() {
            return nextTime;
        }

        public Item setNextTime(String nextTime) {
            this.nextTime = nextTime;
            return this;
        }

        public String getNoRepayAmount() {
            return noRepayAmount;
        }

        public Item setNoRepayAmount(String noRepayAmount) {
            this.noRepayAmount = noRepayAmount;
            return this;
        }

        public List<BillItem> getCollectionOrderDetailVoList() {
            return collectionOrderDetailVoList;
        }

        public Item setCollectionOrderDetailVoList(List<BillItem> collectionOrderDetailVoList) {
            this.collectionOrderDetailVoList = collectionOrderDetailVoList;
            return this;
        }
    }

    private static class BillItem {
        private String tradeNo;
        private Integer period;
        private String repaymentDate;
        private BigDecimal realCapital;
        private BigDecimal interest;
        private BigDecimal lateFee;
        private BigDecimal noRepayAmount;
        private BigDecimal expireAmount;
        private Integer overdueDays;
        private String actualRepaymentDate;
        private BigDecimal deductAmount;
        private BigDecimal paidAmount;

        public String getTradeNo() {
            return tradeNo;
        }

        public BillItem setTradeNo(String tradeNo) {
            this.tradeNo = tradeNo;
            return this;
        }

        public Integer getPeriod() {
            return period;
        }

        public BillItem setPeriod(Integer period) {
            this.period = period;
            return this;
        }

        public String getRepaymentDate() {
            return repaymentDate;
        }

        public BillItem setRepaymentDate(String repaymentDate) {
            this.repaymentDate = repaymentDate;
            return this;
        }

        public String getActualRepaymentDate() {
            return actualRepaymentDate;
        }

        public BillItem setActualRepaymentDate(String actualRepaymentDate) {
            this.actualRepaymentDate = actualRepaymentDate;
            return this;
        }

        public BigDecimal getRealCapital() {
            return realCapital;
        }

        public BillItem setRealCapital(BigDecimal realCapital) {
            this.realCapital = realCapital;
            return this;
        }

        public BigDecimal getInterest() {
            return interest;
        }

        public BillItem setInterest(BigDecimal interest) {
            this.interest = interest;
            return this;
        }

        public BigDecimal getLateFee() {
            return lateFee;
        }

        public BillItem setLateFee(BigDecimal lateFee) {
            this.lateFee = lateFee;
            return this;
        }

        public BigDecimal getNoRepayAmount() {
            return noRepayAmount;
        }

        public BillItem setNoRepayAmount(BigDecimal noRepayAmount) {
            this.noRepayAmount = noRepayAmount;
            return this;
        }

        public BigDecimal getExpireAmount() {
            return expireAmount;
        }

        public BillItem setExpireAmount(BigDecimal expireAmount) {
            this.expireAmount = expireAmount;
            return this;
        }

        public Integer getOverdueDays() {
            return overdueDays;
        }

        public BillItem setOverdueDays(Integer overdueDays) {
            this.overdueDays = overdueDays;
            return this;
        }


        public BigDecimal getDeductAmount() {
            return deductAmount;
        }

        public BillItem setDeductAmount(BigDecimal deductAmount) {
            this.deductAmount = deductAmount;
            return this;
        }

        public BigDecimal getPaidAmount() {
            return paidAmount;
        }

        public BillItem setPaidAmount(BigDecimal paidAmount) {
            this.paidAmount = paidAmount;
            return this;
        }
    }

    private static class CountItem {
        /**
         * 今天分单数
         */
        private Integer totalCount;
        /**
         * 今日完成数
         */
        private Integer completedCount;
        /**
         * 未催回数
         */
        private Integer unfinishedCount;
        /**
         * 完成率
         */
        private String completionRate;
        /**
         * 失效工单数
         */
        private Integer invalidCount;

        public Integer getTotalCount() {
            return totalCount;
        }

        public CountItem setTotalCount(Integer totalCount) {
            this.totalCount = totalCount;
            return this;
        }

        public Integer getCompletedCount() {
            return completedCount;
        }

        public CountItem setCompletedCount(Integer completedCount) {
            this.completedCount = completedCount;
            return this;
        }

        public Integer getUnfinishedCount() {
            return unfinishedCount;
        }

        public CountItem setUnfinishedCount(Integer unfinishedCount) {
            this.unfinishedCount = unfinishedCount;
            return this;
        }

        public String getCompletionRate() {
            return completionRate;
        }

        public CountItem setCompletionRate(String completionRate) {
            this.completionRate = completionRate;
            return this;
        }

        public Integer getInvalidCount() {
            return invalidCount;
        }

        public CountItem setInvalidCount(Integer invalidCount) {
            this.invalidCount = invalidCount;
            return this;
        }
    }
}
